/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.component.dynproperty.support.hibernate;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.jinhe.tss.component.dynproperty.entity.PropertyDef;
import com.jinhe.tss.component.dynproperty.entity.PropertyEntry;
import com.jinhe.tss.component.dynproperty.support.AbstractDynEntity;
import com.jinhe.tss.component.dynproperty.support.DynProperty;
import com.jinhe.tss.core.persistence.IDao;
import com.jinhe.tss.core.persistence.IEntity;
import com.jinhe.tss.core.util.DateUtil;

/** 
 * <p> HibernateDynProperty.java </p> 
 * 
 * 用hibernate方式实现处理动态属性值。
 * 
 * @author Jon.King 2008/04/14 10:18:47 $ 
 */
public class HibernateDynProperty implements DynProperty{
    
    private IDao<IEntity> dao;
 
    public  void init(IDao<IEntity> dao) {
        this.dao = dao; // 注入一个DAO
    }

    /**
     * 获取某个实体的所有(动态属性)
     * @param entityCode
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<PropertyDef> getDynProperties(String entityCode) {
        String hql = "from PropertyDef o where o.entityCode = ? and o.isdyn = 1";
        return (List<PropertyDef>) dao.getEntities(hql, entityCode);
    }
    
    /**
     * 根据动态属性所对应的自定义属性ProPertyDef的ID以及其所属对象的ID
     * @param entityID 
     *                 所属对象的ID
     * @param defID
     *                 所对应的自定义属性ProPertyDef的ID
     */
    @SuppressWarnings("unchecked")
    private List<PropertyEntry> getDynPropertyValues(Long entityId, Long defId) {
        String hql = "from PropertyEntry o where o.entityId = ? and o.defId = ? ";
        return (List<PropertyEntry>) dao.getEntities(hql, entityId, defId);
    }

    /**
     * 保存动态属性值到动态属性值表中。
     * @param entityID 
     *                 所属对象的ID
     * @param defID
     *                 所对应的自定义属性ProPertyDef的ID
     * @param type
     *                 新增属性值的类型
     * @param value
     *                 新增属性的值
     */
    private void saveDynPropertyValue(Long entityId, Long defId, int type, Object value) {
        if( value == null || "".equals(value.toString()) ){
            return;
        }
        PropertyEntry entry = new PropertyEntry();
        entry.setEntityId(entityId);
        entry.setDefId(defId);
        entry.setValue(type, value);

        //如果entry中各个类型的值都为空，则不保存
        if(entry.isVauleNull()) return;
        
        dao.create(entry);
    }

    /**
     * 移除某个实体下某个动态属性的所有动态属性值
     * @param entityID
     * @param defId
     */
    private void removeEntry(Long entityId, Long defId){
        List<PropertyEntry> data = getDynPropertyValues(entityId, defId);
        for(PropertyEntry temp : data) {
            dao.delete(temp);
        }
    }

    @Override
    public AbstractDynEntity saveDynProperti4Entity(AbstractDynEntity entity) {
        List<PropertyDef> dynproperties = this.getDynProperties(entity.getEntityCode());
        Map<String, PropertyDef> keyMappingPropertyDef = new HashMap<String, PropertyDef>();
        for(PropertyDef property : dynproperties ){
            keyMappingPropertyDef.put(property.getKey(), property);
            this.removeEntry(entity.getId(), property.getId());  //保存动态属性前先移除原先的动态属性值
        }    
        
        Map<String, Object> dynpropertiesMap = entity.getDynpropertiesMap();
        for(String key : dynpropertiesMap.keySet()){
            PropertyDef property = keyMappingPropertyDef.get(key);
           
            //如果map中的值动态属性列中没有，则跳过
            if(property == null)  continue;  
            
            Object value = dynpropertiesMap.get(key);
            if(value instanceof Object[]){ // 多值
                Object[] objs = (Object[]) value;
                for(int i = 0; i < objs.length; i++){
                    this.saveDynPropertyValue(entity.getId(), property.getId(), Integer.parseInt(property.getType()), objs[i]);
                }
            }else{
                this.saveDynPropertyValue(entity.getId(), property.getId(), Integer.parseInt(property.getType()), value);
            }
        }       
        
        return entity;
    }
 
    @Override
    public AbstractDynEntity getDynProperti4Entity(AbstractDynEntity entity) {
        List<PropertyDef> dynproperties = this.getDynProperties(entity.getEntityCode()); //取出对象的所有动态属性
        for(PropertyDef property : dynproperties){
            List<PropertyEntry> values = this.getDynPropertyValues(entity.getId(), property.getId());  //取出对象当前记录的所有动态属性值
            List<Object> list = new ArrayList<Object>();
            for(PropertyEntry entry : values){
                Object value = entry.getValue(Integer.parseInt(property.getType()));
                if(value == null) continue;
                
                if(value instanceof Date){
                    value = DateUtil.format((Date)value);
                }
                list.add(value);
            }
            entity.getDynpropertiesMap().put(property.getKey(), list.toArray());
        }        
        return entity;
    }
 
    @Override
    public void removeDynProperti4Entity(AbstractDynEntity entity) {
        List<PropertyDef> dynproperties = this.getDynProperties(entity.getEntityCode());
        for( PropertyDef property : dynproperties ){
            this.removeEntry(entity.getId(), property.getId());
        }
    }
}

